def generate_fat_tree_with_ports(k):
    """
    生成k元胖树拓扑，每个连接包含具体的端口号
    返回连接列表，每个连接为[设备1, 设备2]
    """
    if k % 2 != 0:
        raise ValueError("k must be an even number")

    # 用于存储所有连接
    links = []
    # 用于记录每个交换机已分配的端口数量
    port_counters = {}

    # 创建核心交换机
    core_switches = []
    core_count = (k // 2) ** 2
    for i in range(core_count):
        core_sw = f"c{i}"
        core_switches.append(core_sw)
        port_counters[core_sw] = 1  # 端口从1开始计数

    # 主机计数器
    host_count = 0
    # 交换机列表输出
    switches=[]
    # 处理每个pod
    for pod in range(k):
        # 创建pod内的交换机
        switches.append(f"c{pod}")
        agg_switches = [f"s{pod}-a{i}" for i in range(k // 2)]
        switches.extend(agg_switches )
        edge_switches = [f"s{pod}-e{i}" for i in range(k // 2)]
        switches.extend(edge_switches)
        
        # 初始化端口计数器
        for sw in agg_switches + edge_switches:
            port_counters[sw] = 1

        # 1. 连接汇聚层和边缘层（pod内部）
        for agg_sw in agg_switches:
            for edge_sw in edge_switches:
                # 获取当前端口号并递增
                agg_port = port_counters[agg_sw]
                edge_port = port_counters[edge_sw]
                port_counters[agg_sw] += 1
                port_counters[edge_sw] += 1

                # 添加连接
                links.append([f"{agg_sw}-p{agg_port}", f"{edge_sw}-p{edge_port}"])

        # 2. 连接汇聚层和核心层
        for i, agg_sw in enumerate(agg_switches):
            # 计算该汇聚交换机连接的核心交换机组
            core_group_start = i * (k // 2)
            for j in range(k // 2):
                core_sw = core_switches[core_group_start + j]

                # 获取当前端口号并递增
                agg_port = port_counters[agg_sw]
                core_port = port_counters[core_sw]
                port_counters[agg_sw] += 1
                port_counters[core_sw] += 1

                # 添加连接
                links.append([f"{agg_sw}-p{agg_port}", f"{core_sw}-p{core_port}"])

        # 3. 连接边缘层和主机
        for edge_sw in edge_switches:
            for _ in range(k // 2):  # 每个边缘交换机连接k/2台主机
                # 获取当前端口号并递增
                edge_port = port_counters[edge_sw]
                port_counters[edge_sw] += 1

                # 添加连接（主机使用简写形式）
                links.append([f"h{host_count}", f"{edge_sw}-p{edge_port}"])
                host_count += 1

    return switches,links


# 示例使用（k=4）
k = 4
switches,fat_tree_links = generate_fat_tree_with_ports(k)

# 格式化输出结果
print("[")
for i, link in enumerate(fat_tree_links):
    # 最后一个元素不加逗号
    suffix = "," if i < len(fat_tree_links) - 1 else ""
    print(f"  {link}{suffix}")
print("]")

print("(")
for i,s in enumerate(switches):
    suffix ="," if i< len(switches)-1 else ""
    print(f" {s}{suffix}")
print(")")
